package com.globefrog.framework.log.util;

import java.io.UnsupportedEncodingException;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable;

/**
 * String工具类.
 *
 * @author caijinbang
 * @date 2020-11-08 07:34
 */
public class StringExtUtil extends StringUtils {


  private static Logger logger = LoggerFactory.getLogger(StringUtils.class);

  private static final String CHINESE_UPPER_NUM = "零壹贰叁肆伍陆柒捌玖负";

  private static final String CHINESE_UPPER_UNI = "整分角圆拾佰仟万拾佰仟亿拾佰仟万拾佰仟亿拾佰仟万拾佰仟";

  /**
   * 将指定的字符串转换成double类型数据，如果无法转换则返回null.
   *
   * @param v 要标准化的字符串
   * @return 转换后的int值，或者转换失败后的Null
   */
  public static Double stringToDouble(String v) {
    if (isEmpty(v)) {
      return null;
    }
    try {
      return new Double(v);
    } catch (Exception e) {
      return null;
    }
  }

  /**
   * 将指定的字符串转换成int类型数据，如果无法转换则使用默认值.
   *
   * @param v        要标准化的字符串
   * @param defaultV 默认值
   * @return 转换后的int值，或者转换失败后的默认值
   */
  public static int stringToInt(String v, int defaultV) {
    if (isEmpty(v)) {
      return defaultV;
    }
    try {
      return Integer.parseInt(v);
    } catch (Exception e) {
      return defaultV;
    }
  }

  /**
   * 将指定的字符串转换成long类型数据，如果无法转换则使用默认值.
   *
   * @param v        要标准化的字符串
   * @param defaultV 默认值
   * @return 转换后的long值，或者转换失败后的默认值
   */
  public static long stringToLong(String v, long defaultV) {
    if (isEmpty(v)) {
      return defaultV;
    }
    try {
      return Long.parseLong(v);
    } catch (Exception e) {
      return defaultV;
    }
  }

  /**
   * 字符串转Unicode.
   *
   * @param string 字符串
   * @return Unicode字符
   */
  @Deprecated
  public static String stringToUnicode(String string) {
    try {
      StringBuffer out = new StringBuffer("");
      byte[] bytes = string.getBytes("unicode");
      for (int i = 2; i < bytes.length - 1; i += 2) {
        out.append("u");
        String str = Integer.toHexString(bytes[i + 1] & 0xff);
        for (int j = str.length(); j < 2; j++) {
          out.append("0");
        }
        String str1 = Integer.toHexString(bytes[i] & 0xff);
        out.append(str);
        out.append(str1);
      }
      return out.toString().toUpperCase();
    } catch (UnsupportedEncodingException e) {
      logger.error(e.getMessage(), e);
      return null;
    }
  }

  /**
   * 功能简述 :在一个字符串中查找字符个数.
   *
   * @param source 要被查询的字符串
   * @param target 要查找的字符
   * @return 找到的个数
   */
  public static int subStringCount(String source, char target) {
    // 如果是空指针则返回-1
    if (source == null) {
      return -1;
    }
    if ("".equals(source) || target == 32 || target == 0) {
      return -1;
    }
    int intRet = 0;
    int intPos = source.indexOf(target);
    while (intPos != -1) {
      intRet++;
      intPos = source.indexOf(target, intPos + 1);
    }
    return intRet;
  }

  /**
   * 功能简述 :在一个字符串中查找字符串个数(不区分大小写).
   *
   * @param source 要被查询的字符串
   * @param target 要查找的字符串
   * @return 找到的个数
   */
  public static int subStringCount(String source, String target, boolean caseSensitive) {
    // 如果是空指针则返回-1
    if (source == null || target == null) {
      return -1;
    }
    if ("".equals(source) || "".equals(target)) {
      return -1;
    }
    int intRet = 0;
    int intPos = caseSensitive
        ? source.indexOf(target) : source.toUpperCase().indexOf(target.toUpperCase());
    while (intPos != -1) {
      intRet++;
      intPos = caseSensitive ? source.indexOf(target, intPos + target.length())
          : source.toUpperCase().indexOf(target.toUpperCase(), intPos + target.length());
    }
    return intRet;
  }


  /**
   * 字符串转码.
   *
   * @param src 字符串
   * @return 转码后字符串
   */
  public static String escape(String src) {
    int i;
    char j;
    StringBuffer tmp = new StringBuffer();
    tmp.ensureCapacity(src.length() * 6);
    for (i = 0; i < src.length(); i++) {
      j = src.charAt(i);
      if (Character.isDigit(j) || Character.isLowerCase(j) || Character.isUpperCase(j)) {
        tmp.append(j);
      } else if (j < 256) {
        tmp.append("%");
        if (j < 16) {
          tmp.append("0");
        }
        tmp.append(Integer.toString(j, 16));
      } else {
        tmp.append("%u");
        tmp.append(Integer.toString(j, 16));
      }
    }
    return tmp.toString();
  }


  /**
   * 字符串解码.
   *
   * @param src 字符串
   * @return 解码后的字符串
   */
  public static String unescape(String src) {
    StringBuilder tmp = new StringBuilder();
    tmp.ensureCapacity(src.length());
    int lastPos = 0;
    int pos = 0;
    char ch;
    while (lastPos < src.length()) {
      pos = src.indexOf("%", lastPos);
      if (pos == lastPos) {
        if (src.charAt(pos + 1) == 'u') {
          ch = (char) Integer.parseInt(src.substring(pos + 2, pos + 6), 16);
          tmp.append(ch);
          lastPos = pos + 6;
        } else {
          ch = (char) Integer.parseInt(src.substring(pos + 1, pos + 3), 16);
          tmp.append(ch);
          lastPos = pos + 3;
        }
      } else {
        if (pos == -1) {
          tmp.append(src.substring(lastPos));
          lastPos = src.length();
        } else {
          tmp.append(src.substring(lastPos, pos));
          lastPos = pos;
        }
      }
    }
    return tmp.toString();
  }


  /**
   * url请求参数拼接,将变量值不为空的参数组成字符串.
   *
   * @param returnStr  返回字符串
   * @param paramKey   key
   * @param paramValue value
   * @return 拼接的参数
   */
  public static String appendParam(String returnStr, String paramKey, String paramValue) {
    if (!"".equals(returnStr)) {
      if (paramValue != null && !"".equals(paramValue)) {
        returnStr = returnStr + "&" + paramKey + "=" + paramValue;
      }
    } else {
      if (paramValue != null && !"".equals(paramValue)) {
        returnStr = paramKey + "=" + paramValue;
      }
    }
    return returnStr;
  }


  /**
   * 以元为单位的数据转化为以分为单位的数据.
   *
   * @param input 输入
   * @return 分
   */
  public static String formatYuanToFen(String input) {
    String out = "";
    NumberFormat ft = NumberFormat.getInstance();
    Number nbInput;
    try {
      nbInput = ft.parse(input);
      double fInput = nbInput.doubleValue() * 100.0;
      ft.setGroupingUsed(false);
      ft.setMaximumFractionDigits(0);
      out = ft.format(fInput);
    } catch (ParseException e) {
      logger.error(e.getMessage(), e);
    }
    return out;
  }

  /**
   * 以分为单位的数据转化为以元为单位的数据.
   *
   * @param input 输入
   * @return 元
   */
  public static String formatFenToYuan(String input) {
    String out = "";
    NumberFormat ft = NumberFormat.getInstance();
    Number nbInput;
    try {
      nbInput = ft.parse(input);
      double fInput = nbInput.doubleValue() / 100.0;
      ft.setGroupingUsed(false);
      out = ft.format(fInput);
    } catch (ParseException e) {
      logger.error(e.getMessage(), e);
    }
    return out;
  }

  /**
   * 随机字符串.
   *
   * @param size 长度
   * @return 随机字符串
   */
  public static String getRandomString(int size) {
    char[] c = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'q', 'w', 'e', 'r', 't', 'y', 'u',
        'i', 'o', 'p',
        'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm'};
    // 初始化随机数产生器
    Random random = new Random();
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < size; i++) {
      sb.append(c[Math.abs(random.nextInt(Integer.MAX_VALUE)) % c.length]);
    }
    return sb.toString();
  }

  /**
   * 随机字符串(数字).
   *
   * @param size 长度
   * @return 随机字符串
   */
  public static String getRandomNumber(int size) {
    char[] c = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
    // 初始化随机数产生器
    Random random = new Random();
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < size; i++) {
      sb.append(c[Math.abs(random.nextInt(Integer.MAX_VALUE)) % c.length]);
    }
    return sb.toString();
  }

  /**
   * 验证指定的字串是否IP地址 ip形如192.168.0.1则返回true 否则返回false。
   *
   * @param ip ip
   * @return 是否是ip格式地址
   */
  public static boolean isIp(String ip) {
    Pattern patt = Pattern.compile("^([01]?[0-9][0-9]|[01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])"
        + "\\.([01]?[0-9][0-9]|[01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])"
        + "\\.([01]?[0-9][0-9]|[01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])"
        + "\\.([01]?[0-9][0-9]|[01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$");
    Matcher mat = patt.matcher(ip);
    return mat.matches();
  }

  /**
   * 返回IP的指定部分字串 如调用getOnePartOfIPDomain("192.168.0.1", 2) 返回168
   *
   * @param ip    ip
   * @param index 位置
   * @return
   */
  public static String getOnePartOfIP(String ip, int index) {
    String result = null;
    if (!isIp(ip)) {
      return null;
    }
    String[] ipArr = ip.split("\\.");
    if (index <= ipArr.length) {
      result = ipArr[index - 1];
    }
    return result;
  }


  /**
   * 判断字符串中的字符是否均为数字 如"123990"返回true,"123a"返回false.
   *
   * @param str 字符串
   * @return 是否全是数字
   */
  public static boolean isAllNumbric(String str) {
    if (str == null) {
      return false;
    }
    for (int i = 0; i < str.length(); i++) {
      if (str.charAt(i) < '0' || str.charAt(i) > '9') {
        return false;
      }
    }
    return true;
  }

  /**
   * 价格转中文大写.
   *
   * @param priceNum 数字价格
   * @return 中文价格大写
   */
  public static String prieToChineseUpper(String priceNum) {
    int length = priceNum.length();
    if (length > 27) {
      // 包括小数点和2位小数
      return "数值溢出";
    }
    // 转换前的字符串
    StringBuffer sb = new StringBuffer();
    sb.append(priceNum);
    // 删除小数点
    sb.deleteCharAt(length - 3);
    --length;
    // 转换后的字符串
    StringBuffer sa = new StringBuffer();
    if (sb.charAt(length - 1) == '0') {
      // 分位为零则尾部加'整'
      sa.insert(0, '整');
    }
    boolean zero = false;
    boolean a = false;
    boolean b = false;
    int n = 0;
    for (int i = 1; i <= length; i = i + 1) {
      // 数值
      n = sb.charAt(length - i) - '0';
      if (i == 7 || i == 15) {
        // 万位、万亿位是零
        b = n == 0;
      }
      if ((i > 7) & (i < 11) || (i > 15) & (i < 19)) {
        // 万-亿位、或亿-亿位之间全是零
        b = (n == 0) & b;
      }
      // 万亿、亿、万、元、分位为0时不写'零'
      a = (i == 1 || i == 3 || i == 7 || i == 11 || i == 15 || i == 19 || i == 23);

      if (n > 0 || (i > 1 & a)) {
        if ((i == 11 || i == 19) & b) {
          // 用'亿'覆盖'万'
          sa.setCharAt(0, '亿');
        } else {
          // 插入单位
          sa.insert(0, CHINESE_UPPER_UNI.charAt(i));
        }
      }
      if (!(n == 0 & (zero || a))) {
        // 插入数值
        sa.insert(0, CHINESE_UPPER_NUM.charAt(n));
      }
      zero = n == 0;
    }
    if (n == 0) {
      sa.insert(0, '零');
    }
    return sa.toString();
  }

  public static boolean hasText(@Nullable String str) {
    return (str != null && !str.isEmpty() && containsText(str));
  }

  private static boolean containsText(CharSequence str) {
    int strLen = str.length();
    for (int i = 0; i < strLen; i++) {
      if (!Character.isWhitespace(str.charAt(i))) {
        return true;
      }
    }
    return false;
  }
}
